Login dark
author: 零贰
title: 很方便的串口类 CComAccess
date: 2009-01-20 12:49:38
category: [编程代码]
tags: [VC,串口,代码,源码]
feature: http://image.cool02.com/blogimages/code.jpg

<p>       网上这方面三方类多如牛毛,真不知道用哪个好,不过不管用哪个,一定要在严格检查完善后再使用,不然给以后通信埋下隐患,只会让以后的调试会更痛苦!<!--more-->

</p> <p>ComAccess.h</p> <pre><ol><li>//////////////////////////////////////////////////////////////////////  <li>//  <li>// ComAccess.h: interface for the CComAccess class.  <li>//  <li>//////////////////////////////////////////////////////////////////////  <li> <li>#if !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_)  <li>#define AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_  <li> <li>#if _MSC_VER > 1000  <li>#pragma once  <li>#endif // _MSC_VER > 1000  <li> <li> <li>class CComAccess   <li>{  <li>private:  <li> <li>    HANDLE      m_hCom; // Device handle   <li> <li>    OVERLAPPED  m_ov;   // A structure that contains informations which are  <li>                        // used for asynchronous input and output operations  <li> <li>    TCHAR       m_lpszErrorMessage[256];  <li> <li>public:  <li> <li>    CComAccess();  <li>    CComAccess(LPCSTR lpszPortNum);  <li> <li>    ~CComAccess();  <li>                                    // For more definitions see <winbase.h>  <li>    BOOL    Open(LPCSTR lpszPortNum = "com1",  <li>                 DWORD  dwBaudRate  = CBR_9600,   <li>                 BYTE   byParity    = NOPARITY,  <li>                 BYTE   byStopBits  = ONESTOPBIT,  <li>                 BYTE   byByteSize  = 8);  <li> <li>    VOID    Close();  <li>      <li>    DWORD   WriteData(LPCVOID pdata, DWORD len);  <li>    DWORD   ReadData(LPVOID  pdest, DWORD len, DWORD dwMaxWait = 500);  <li> <li>    LPSTR   GetErrorMessage(VOID) { return m_lpszErrorMessage; }  <li> <li>private:  <li> <li>    VOID    ErrorToString(LPCSTR lpszMessage);  <li> <li>    BOOL    IsNT(VOID);  <li>};  <li> <li>#endif // !defined(AFX_COMACCESS_H__F15FFC6E_D059_4E57_97CD_A672C05FF9B7__INCLUDED_) </li></ol></pre>

<p>ComAccess.cpp</p>

<ol><li>//////////////////////////////////////////////////////////////////////  <li>//  <li>// ComAccess.cpp: implementation of the CComAccess class.  <li>//  <li>//////////////////////////////////////////////////////////////////////  <li> <li>#include "stdafx.h"  <li>#include "ComAccess.h"  <li> <li>#ifdef _DEBUG  <li>#undef THIS_FILE  <li>static char THIS_FILE[]=__FILE__;  <li>#define new DEBUG_NEW  <li>#endif  <li> <li>//////////////////////////////////////////////////////////////////////  <li>// Construction/Destruction  <li>//////////////////////////////////////////////////////////////////////  <li> <li>CComAccess::CComAccess(VOID)  <li>{  <li>    m_hCom = 0;  <li>    m_lpszErrorMessage[0] = '0';  <li>    ZeroMemory(&m_ov, sizeof(m_ov));  <li>}  <li> <li> <li>CComAccess::CComAccess(LPCSTR lpszPortNum)  <li>{   <li>    CComAccess::CComAccess();  <li>    CComAccess::Open(lpszPortNum);   <li>}  <li> <li>CComAccess::~CComAccess()  <li>{  <li>    Close();  <li>}  <li> <li>////////////////////////////////////////////////////////////////////////////////////////  <li>//   <li>//  Function:      Open(LPCSTR lpszPortNum,  <li>//                      DWORD  dwBaudRate,   <li>//                      BYTE   byParity,  <li>//                      BYTE   byStopBits,  <li>//                      BYTE   byByteSize)  <li>//  <li>//  Return value:  BOOL TRUE or FALSE  <li>//  <li> <li>BOOL CComAccess::Open(LPCSTR lpszPortNum,   <li>                     DWORD  dwBaudRate,   <li>                     BYTE   byParity,  <li>                     BYTE   byStopBits,  <li>                     BYTE   byByteSize)  <li>{  <li>    DCB  dcb; // structure that defines the control setting for a serial communications device  <li>    BOOL bSuccess;  <li>      <li>    m_hCom = CreateFile(lpszPortNum,           // pointer to name of the file  <li>                        GENERIC_READ|GENERIC_WRITE, // access mode  <li>                        0,                     // comm devices must be opened w/exclusive-access   <li>                        NULL,                  // no security attributs   <li>                        OPEN_EXISTING,         // comm devices must use OPEN_EXISTING   <li>                        FILE_FLAG_OVERLAPPED,  // overlapped I/O  <li>                        NULL);                 // hTemplate must be NULL for comm devices   <li> <li>    if ( m_hCom == INVALID_HANDLE_VALUE )   <li>    {  <li>        // handle the error  <li>        CComAccess::ErrorToString("Open(): CreateFile() failed, invalid handle value");  <li>          <li>        return FALSE;  <li>    }  <li> <li>    //  <li>    // Omit the call to SetupComm to use the default queue sizes.  <li>    // Get the current configuration.  <li>    //  <li>   <li>    bSuccess = GetCommState(m_hCom, &dcb);  <li> <li>    if ( ! bSuccess )   <li>    {  <li>        // Handle the error.  <li>        CComAccess::ErrorToString("Open(): GetCommState() failed");  <li>        CComAccess::Close();  <li> <li>        return FALSE;  <li>    }  <li> <li>    //  <li>    // Fill in the DCB: baud=9600, 8 data bits, no parity, 1 stop bit are default parameters  <li>    //  <li> <li>    dcb.BaudRate = dwBaudRate;  <li>    dcb.ByteSize = byByteSize;  <li>    dcb.Parity   = byParity;  <li>    dcb.StopBits = byStopBits;  <li>      <li>    bSuccess = SetCommState(m_hCom, &dcb);  <li> <li>    if ( ! bSuccess )   <li>    {  <li>        // Handle the error.   <li>        CComAccess::ErrorToString("Open(): SetCommState() failed");  <li>        CComAccess::Close();  <li> <li>        return FALSE;  <li>    }  <li> <li>    return TRUE;  <li>}  <li> <li> <li>////////////////////////////////////////////////////////////////////////////////////////  <li>//   <li>//  Function:      Close(VOID)  <li>//  <li>//  Return value:  VOID  <li>//  <li> <li>VOID CComAccess::Close()  <li>{  <li>    if ( m_hCom > 0 )  <li>    {  <li>        CloseHandle(m_hCom);  <li>    }  <li> <li>    m_hCom = 0;   <li>}  <li> <li>////////////////////////////////////////////////////////////////////////////////////////  <li>//   <li>//  Function:     WriteData(LPCVOID pdata,   <li>//                          DWORD   len)  <li>//  <li>//  Return value:  DWORD -1 failed, above, num written bytes  <li>//  <li> <li>DWORD CComAccess::WriteData(LPCVOID pdata,   <li>                           DWORD   len)  <li>{  <li>    BOOL  bSuccess;  <li>    DWORD written = 0;  <li> <li>    if ( len < 1 )  <li>        return(0);  <li> <li>    // create event for overlapped I/O  <li>    m_ov.hEvent = CreateEvent(NULL,   // pointer to security attributes   <li>                              FALSE,   // flag for manual-reset event   <li>                              FALSE,  // flag for initial state   <li>                              "");    // pointer to event-object name   <li> <li>    if ( m_ov.hEvent == INVALID_HANDLE_VALUE )  <li>    {  <li>        // Handle the error.  <li>        CComAccess::ErrorToString("WriteData(): CreateEvent() failed");  <li>        <li>        return(-1);  <li>    }  <li> <li>    bSuccess = WriteFile(m_hCom,   // handle to file to write to    <li>                         pdata,    // pointer to data to write to file   <li>                         len,      // number of bytes to write   <li>                         &written, // pointer to number of bytes written   <li>                         &m_ov);   // pointer to structure needed for overlapped I/O  <li> <li> <li>    if ( CComAccess::IsNT() )  <li>    {  <li>        bSuccess = GetOverlappedResult(m_hCom, &m_ov, &written, TRUE);  <li> <li>        if ( ! bSuccess )  <li>        {  <li>            // Handle the error.  <li>            CloseHandle(m_ov.hEvent);  <li>            CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed");  <li> <li>            return(-1);  <li>        }  <li>    }  <li>    else <li>    if ( len != written )  <li>    {  <li>        // Handle the error.  <li>        CloseHandle(m_ov.hEvent);  <li>        CComAccess::ErrorToString("WriteData(): WriteFile() failed");  <li> <li>        return(-1);  <li>    }  <li> <li>    CloseHandle(m_ov.hEvent);  <li> <li>    return written;  <li>}  <li> <li>////////////////////////////////////////////////////////////////////////////////////////  <li>//   <li>//  Function:      ReadData(LPVOID pdest,   <li>//                          DWORD  len,   <li>//                          DWORD  dwMaxWait)  <li>//  <li>//  Return value:  DWORD -1 failed, above, num read bytes         <li>//  <li> <li>DWORD CComAccess::ReadData(LPVOID pdest,   <li>                          DWORD  len,   <li>                          DWORD  dwMaxWait)  <li>{  <li>    BOOL  bSuccess;  <li>    DWORD result = 0,  <li>          read   = 0, // num read bytes  <li>          mask   = 0; // a 32-bit variable that receives a mask   <li>                      // indicating the type of event that occurred  <li> <li>    if ( len < 1 ) return(0);  <li> <li>    // create event for overlapped I/O  <li> <li>    m_ov.hEvent = CreateEvent(NULL,   // pointer to security attributes   <li>                              FALSE,   // flag for manual-reset event   <li>                              FALSE,  // flag for initial state   <li>                              "");    // pointer to event-object name   <li> <li>    if ( m_ov.hEvent == INVALID_HANDLE_VALUE )  <li>    {  <li>        // Handle the error.  <li>        CComAccess::ErrorToString("ReadData(): CreateEvent() failed");  <li>        <li>        return(-1);  <li>    }  <li> <li>    // Specify here the event to be enabled  <li> <li>    bSuccess = SetCommMask(m_hCom, EV_RXCHAR);  <li> <li>    if ( ! bSuccess )  <li>    {  <li>        // Handle the error.  <li>        CloseHandle(m_ov.hEvent);  <li>        CComAccess::ErrorToString("ReadData(): SetCommMask() failed");  <li>        <li>        return(-1);  <li>    }  <li> <li>      <li>    // WaitForSingleObject  <li> <li>    bSuccess = WaitCommEvent(m_hCom, &mask, &m_ov);  <li> <li>    if ( ! bSuccess )  <li>    {  <li>        int err = GetLastError();  <li> <li>        if ( err == ERROR_IO_PENDING)  <li>        {  <li>            result = WaitForSingleObject(m_ov.hEvent, dwMaxWait);  //wait dwMaxWait  <li>                                                // milli seconds before returning  <li>            if ( result == WAIT_FAILED )  <li>            {  <li>                // Handle the error.  <li>                CloseHandle(m_ov.hEvent);  <li>                CComAccess::ErrorToString("ReadData(): WaitForSingleObject() failed");  <li>        <li>                return(-1);  <li>            }  <li>        }  <li>    }  <li>      <li>    // The specified event occured?  <li>      <li>    if ( mask & EV_RXCHAR)   <li>    {  <li>        bSuccess = ReadFile(m_hCom, // handle of file to read   <li>                            pdest,  // address of buffer that receives data   <li>                            len,    // number of bytes to read   <li>                            &read,  // address of number of bytes read   <li>                            &m_ov); // address of structure for data   <li> <li>        if ( CComAccess::IsNT() )  <li>        {  <li>            bSuccess = GetOverlappedResult(m_hCom, &m_ov, &read, TRUE);  <li> <li>            if ( ! bSuccess )  <li>            {  <li>                // Handle the error.  <li>                CloseHandle(m_ov.hEvent);  <li>                CComAccess::ErrorToString("WriteData(): GetOverlappedResult() failed");  <li> <li>                return(-1);  <li>            }  <li>        }  <li>        else <li>        if ( ! bSuccess )  <li>        {  <li>            // Handle the error.  <li>            CloseHandle(m_ov.hEvent);  <li>            CComAccess::ErrorToString("ReadData(): ReadFile() failed");  <li> <li>            return(-1);  <li>        }  <li>    }  <li>    else <li>    {  <li>        // Handle the error.  <li>        CloseHandle(m_ov.hEvent);  <li>        wsprintf(m_lpszErrorMessage, "Error ReadData(): No EV_RXCHAR occuredn");  <li> <li>        return(-1);  <li>    }  <li>      <li>    CloseHandle(m_ov.hEvent);  <li>      <li>    return read;  <li>}  <li> <li>////////////////////////////////////////////////////////////////////////////////////////  <li>//   <li>//  Function:      ErrorToString(LPCSTR lpszMessage)  <li>//  <li>//  Return value:  VOID  <li>//  <li> <li>VOID CComAccess::ErrorToString(LPCSTR lpszMessage)  <li>{  <li>    LPVOID lpMessageBuffer;  <li>    DWORD  error = GetLastError();  <li> <li>    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |  <li>                  FORMAT_MESSAGE_FROM_SYSTEM,      // source and processing options  <li>                  NULL,                            // pointer to message source  <li>                  error,                           // requested message identifie  <li>                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // the user default language.  <li>                  (LPTSTR) &lpMessageBuffer,       // pointer to message buffer  <li>                  0,                               // maximum size of message buffer  <li>                  NULL);                           // address of array of message inserts   <li> <li>    // and copy it in our error string  <li>    wsprintf(m_lpszErrorMessage,"%s: (%d) %sn", lpszMessage, error, lpMessageBuffer);  <li> <li>    LocalFree(lpMessageBuffer);  <li>}  <li> <li>////////////////////////////////////////////////////////////////////////////////////////  <li>//   <li>//  Function:     IsNT(VOID)  <li>//  <li>//  Return value: BOOL True or False  <li>//  <li> <li>BOOL CComAccess::IsNT(VOID)  <li>{  <li>    OSVERSIONINFO osvi;  <li>      <li>    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);  <li>      <li>    GetVersionEx(&osvi);  <li> <li>    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)   <li>    {  <li>        return TRUE;  <li>    }  <li>    else <li>    {  <li>        return FALSE;  <li>    }  <li>} </li></ol>